{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Rotor 37 Tutorial\n",
    "NASA Rotor 37 is a transonic axial-flow compressor rotor that has been widely studied for aerodynamic research and computational fluid dynamics (CFD) validation. Originally developed as part of a stage in a compressor used for jet engines, Rotor 37 operates at a design speed of 17,188 RPM and features a pressure ratio of about 2.1. It has 36 blades with a tip Mach number of approximately 1.38, making it ideal for studying shockwave interactions, boundary layer behavior, and overall compressor performance. The rotor has been extensively used in both experimental and numerical simulations to improve high-speed compressor designs and validate turbulence models in aerospace engineering.\n",
    "\n",
    "[Rotor 37 Data](https://turbmodels.larc.nasa.gov/Other_exp_Data/rotor37_exp.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PyTurbo-Aero could be used to import the geometry for rotor 37 allowing the user to add features such as waves or shift the airfoil along the passage or even change the passage. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install pyturbo-aero"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!git clone https://github.com/nasa/pyturbo-aero.git"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!cp pyturbo-aero/tutorials/rotor37/* ."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Importing the Airfoil to PyTurbo-Aero"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Headers \n",
    "from pyturbo.aero import Airfoil2D,Airfoil3D,Passage2D\n",
    "from pyturbo.helper import bezier, bezier3, csapi\n",
    "import numpy as np\n",
    "import copy\n",
    "import matplotlib.pyplot as plt "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Importing the coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "files = ['R37_profile01.csv','R37_profile02.csv','R37_profile03.csv','R37_profile04.csv','R37_profile05.csv','R37_profile06.csv']\n",
    "xss = np.zeros(shape=(len(files),151)) # 5 profiles, each one is 151 points\n",
    "yss = np.zeros(shape=(len(files),151))\n",
    "zss = np.zeros(shape=(len(files),151))\n",
    "\n",
    "xps = np.zeros(shape=(len(files),151))\n",
    "yps = np.zeros(shape=(len(files),151))\n",
    "zps = np.zeros(shape=(len(files),151))\n",
    "data = list()\n",
    "cx = np.zeros(shape=(len(files),1)); cy = np.zeros(shape=(len(files),1)); cz = np.zeros(shape=(len(files),1))\n",
    "airfoils = list()\n",
    "for i,f in enumerate(files):\n",
    "    data = np.loadtxt(f,skiprows=1,delimiter=',')\n",
    "    xss[i,:] = data[:151,0]\n",
    "    yss[i,:] = data[:151,1]\n",
    "    zss[i,:] = data[:151,2]\n",
    "    xps[i,:] = np.flipud(data[150:,0])\n",
    "    yps[i,:] = np.flipud(data[150:,1])\n",
    "    zps[i,:] = np.flipud(data[150:,2])\n",
    "    \n",
    "    # Airfoil 3D - Centroid \n",
    "    cx[i] = np.hstack([xps[i,:],xss[i,:]]).mean()\n",
    "    cz[i] = np.hstack([zps[i,:],zss[i,:]]).mean()\n",
    "    cy[i] = np.hstack([yps[i,:],yss[i,:]]).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating the Airfoil 3D geometry "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Creating the Airfoil 3D \n",
    "nspan = 100\n",
    "R37 = Airfoil3D([],[],0)\n",
    "R37.b3 = bezier3(cx,cy,cz)\n",
    "R37.shft_xss = np.zeros(shape=(nspan,151))\n",
    "R37.shft_yss = np.zeros(shape=(nspan,151))\n",
    "\n",
    "R37.shft_xps = np.zeros(shape=(nspan,151))\n",
    "R37.shft_yps = np.zeros(shape=(nspan,151))\n",
    "\n",
    "R37.shft_zss = np.zeros(shape=(nspan,151))\n",
    "R37.shft_zps = np.zeros(shape=(nspan,151))\n",
    "\n",
    "for i in range(151):        # Lets get a higher resolution airfoil\n",
    "    z = np.linspace(zss[0,i],zss[-1,i],nspan)\n",
    "    R37.shft_xss[:,i]= csapi(zss[:,i],xss[:,i],z)\n",
    "    R37.shft_yss[:,i]= csapi(zss[:,i],yss[:,i],z)\n",
    "    R37.shft_zss[:,i]= z\n",
    "    \n",
    "    z = np.linspace(zps[0,i],zps[-1,i],nspan)\n",
    "    R37.shft_xps[:,i]= csapi(zps[:,i],xps[:,i],z)\n",
    "    R37.shft_yps[:,i]= csapi(zps[:,i],yps[:,i],z)\n",
    "    R37.shft_zps[:,i]= z\n",
    "\n",
    "R37.control_x_ss = xss\n",
    "R37.control_y_ss = yss\n",
    "R37.control_x_ps = xps\n",
    "R37.control_y_ps = yps\n",
    "R37.xss = copy.deepcopy(R37.shft_xss)\n",
    "R37.yss = copy.deepcopy(R37.shft_yss)\n",
    "R37.xps = copy.deepcopy(R37.shft_xps)\n",
    "R37.yps = copy.deepcopy(R37.shft_yps)\n",
    "R37.bImportedBlade = True\n",
    "R37.stackType=2 # Centroid\n",
    "R37.span = max(z)-min(z)\n",
    "R37.spanwise_spline_fit()\n",
    "R37.nspan = nspan\n",
    "R37.plot3D()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import the hub and shroud curves\n",
    "I think the units are in inches. I don't like inches. I don't like fractions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hub = np.loadtxt('hub_R37.dat')\n",
    "shroud = np.loadtxt('shroud_R37.dat')\n",
    "passage = Passage2D(airfoil_array=[R37],spacing_array=[0])\n",
    "passage.add_endwalls(zhub=hub[:,0],rhub=hub[:,2],zshroud=shroud[:,0],rshroud=shroud[:,2])\n",
    "passage.blade_fit(hub[:,0].min())\n",
    "passage.plot2D()"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
